package com.ghostmonk.organic.data
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.geom.Point;
	import flash.ui.Keyboard;
	
	public class BasicPerlinData extends Sprite
	{	
		
		public static const TOGGLE_VISIBILITY:String = "toggleVisibility"
		public static const VALUE_CHANGE:String = "valueChange"
		
		private var _bitmapData:BitmapData;
		private var _bitmap:Bitmap;
		private var _points:Array = new Array();
		
		private const WIDTH:Number = 116;
		private const HEIGHT:Number = 100;
		private var _baseX:Number = 50;
		private var _baseY:Number = 50;
		private var _octaves:uint = 3;
		private var _randomSeed:int = 10;
		private var _stitch:Boolean = false;
		private var _fractalNoise:Boolean = false;
		private var _greyScale:Boolean = false;
		private var _channelOptions:uint = 6;
		private var _isBitmapVisible:Boolean = false;
		private var _speed:Number = 1;
		
		public function setBaseX		(value:Number)	:void	{	_baseX = value;			}
		public function setBaseY		(value:Number)	:void	{	_baseY = value;			}
		public function setRandomSeed	(value:int)		:void	{	_randomSeed = value;	}
		public function setStitch		(value:Boolean)	:void	{	_stitch = value;		}
		public function setFractalNoise	(value:Boolean)	:void	{	_fractalNoise = value;	}
		public function setGreyScale	(value:Boolean)	:void	{	_greyScale = value;		}
		
		public function getBaseX()			:Number		{	return _baseX;			}
		public function getBaseY()			:Number		{	return _baseY;			}
		public function getRandomSeed()		:int		{	return _randomSeed;		}
		public function getStitch()			:Boolean	{	return _stitch;			}
		public function getFractalNoise()	:Boolean	{	return _fractalNoise;	}
		public function getGreyScale()		:Boolean	{	return _greyScale;		}
		public function getSpeed()			:Number		{  	return _speed;			}
		public function getOctaves()		:uint		{	return _octaves;		}
		
		private var _alterValue:Number = 0;
		
		public function BasicPerlinData()
		{			
			_bitmapData = new BitmapData(WIDTH,HEIGHT,false,0xff000000);
			_bitmap = new Bitmap(_bitmapData);
			//addChild(_bitmap);
			_bitmap.scaleX = _bitmap.scaleY = 4;
			_bitmap.alpha = 1;
			
			for(var i:int = 0; i<_octaves; i++)
			{
				var point:Point = new Point(0,0);
				_points.push(point);
			}
			createPerlinBitmap();
			
			addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
		}
		
		private function onAddedToStage(e:Event):void
		{
			removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
			stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
		}
		
		public function createPerlinBitmap():void
		{	
			_points[0].x += 1*_speed;
			_points[1].y += 1*_speed;
			_points[2].x += 1*_speed;
			_bitmapData.perlinNoise(_baseX,_baseY,_octaves,_randomSeed,_stitch,_fractalNoise,_channelOptions,_greyScale,_points);	
		}
		
		public function getDataPoint(x:int,y:int):Number
		{ 
			var dataRange:Number = _bitmapData.getPixel(x,y)/16711422*255;
			return dataRange;
		}
		
		private function onKeyDown(e:KeyboardEvent):void
		{
			stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
			stage.removeEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
			
			switch(e.charCode)
			{
				case 49: _channelOptions = 1; break;
				case 50: _channelOptions = 2; break;
				case 51: _channelOptions = 3; break;
				case 52: _channelOptions = 4; break;
				case 53: _channelOptions = 5; break;
				case 54: _channelOptions = 6; break;
				case 55: _channelOptions = 7; break;
				case 120: _alterValue = 1; break;
				case 121: _alterValue = 2; break;
				case 114: _alterValue = 3; break;
				case 115: _alterValue = 4; break;
				case 102: _alterValue = 5; break;
				case 103: _alterValue = 6; break;
				case 111: _alterValue = 7; break;
				case 118: _alterValue = 8; break;
				case 48: toggleBitmapVisibility(); break;
			}
			 
			switch(e.keyCode)
			{
				case Keyboard.UP:
				case Keyboard.RIGHT:
					switch(_alterValue)
					{
						case 1: _baseX+=10;				break;
						case 2: _baseY+=10;				break;
						case 3: _randomSeed++; 			break;
						case 4: _stitch = true;			break;
						case 5: _fractalNoise = true;	break;
						case 6: _greyScale = true;		break;
						case 7: _octaves ++;			break;
						case 8: _speed += 0.1;			break;
					}
				break;
				
				case Keyboard.DOWN: 
				case Keyboard.LEFT:
					switch(_alterValue)
					{
						case 1: _baseX-=10; 			break;
						case 2: _baseY-=10; 			break;
						case 3: _randomSeed--; 			break;
						case 4: _stitch = false;		break;
						case 5: _fractalNoise = false;	break;
						case 6: _greyScale = false;		break;
						case 7: _octaves--;				break;
						case 8: _speed-= 0.1;			break;
					}
				break;
			}
			createPerlinBitmap();
			dispatchEvent(new Event(VALUE_CHANGE));
		}
		
		private function onKeyUp(e:KeyboardEvent):void
		{
			stage.removeEventListener(KeyboardEvent.KEY_UP, onKeyUp);
			stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
		}
		
		private function toggleBitmapVisibility():void
		{
			_isBitmapVisible = !_isBitmapVisible;
			
			_isBitmapVisible ? addChild(_bitmap) : removeChild(_bitmap);
			
			dispatchEvent(new Event(TOGGLE_VISIBILITY));
		}
		
	}
}